package io.traveller.apiGateway.client;

import io.traveller.apiGateway.client.discovery.DiscoveryClientRouteExtLocator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.discovery.event.HeartbeatEvent;
import org.springframework.cloud.client.discovery.event.HeartbeatMonitor;
import org.springframework.cloud.client.discovery.event.InstanceRegisteredEvent;
import org.springframework.cloud.client.discovery.event.ParentHeartbeatEvent;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * Route服务端配置
 *
 * Created by yunai on 16/9/26.
 */
@Configuration
public class RouteServerConfiguration {

    @Bean
    public RefreshListener refreshListener() {
        return new RefreshListener();
    }

    @Bean
    public DiscoveryClientRouteExtLocator discoveryClientRouteExtLocator() {
        return new DiscoveryClientRouteExtLocator();
    }

    /**
     * 刷新服务端路由配置
     */
    private static class RefreshListener implements ApplicationListener<ApplicationEvent> {

        private final HeartbeatMonitor monitor = new HeartbeatMonitor();

        @Autowired
        private DiscoveryClientRouteExtLocator locator;

        @Override
        public void onApplicationEvent(ApplicationEvent event) {
            if (event instanceof InstanceRegisteredEvent) {
                reset();
            } else if (event instanceof ParentHeartbeatEvent) {
                ParentHeartbeatEvent e = (ParentHeartbeatEvent) event;
                resetIfNeeded(e.getValue());
            } else if (event instanceof HeartbeatEvent) {
                HeartbeatEvent e = (HeartbeatEvent) event;
                resetIfNeeded(e.getValue());
            }
        }

        private void resetIfNeeded(Object value) {
            if (this.monitor.update(value)) {
                reset();
            }
        }

        private void reset() {
            locator.refresh();
        }

    }

}
